﻿﻿/**@description IGrid 组件*/
(function (IGrid) {
	var config = function () { 
		return {
			width: null,
	        height: null,
	        showPager: true,
	        showStatus: false,
	        showFirstEditor: true,
	        showColumnIcon: true,
	        customSetting: false,
			wrapHead: true,
			headTip: false,
			// 验证修改数据
			isValidUpdate: true,
	        pagerOp: {
	        	pageInf: {
	        		 pageSize: Ccay.UI.Config.pager.defaultSize,
					 curPage: 1,
					 totalRows: 0,
					 totalPage: null
	        	},
	        	pageSizes: [].concat(Ccay.UI.Config.pager.pageSizes)
	        },
	        autoScroll: true,
	        allowSort: true,
	        allowResize: true,
	        allowFreezen: true,
	        remoteSort: false,
	        showSeq: true,
	        serialSeq: true,		//seq是否连续显示
	        columns: null,
	        rowAttr: {},
	        rowClass: ["grid-row"],
	        rowCodeBegin: [],
	        rowCodeEnd: [],
	        rowHeight: 24,
	        customHead: null,    //自定义表头
	        autoLoad: true,
	        fnSorted: null,
	        fnSelected: null,
	        fnRenderRow: null,
	        noResultI18n:null
		};
	};

   var factory = IGrid.Factory = {
   		/** @description 初始化内置事件委托对象
   		 *  @param {Object} op igrid的参数设置
   		 */
    	initHandler: function (op) {
    		$.extend(op.handler,{
    			setColumn:$.Callbacks(),
    			beforeLoad:$.Callbacks(),
    			click:$.IAdapter(),
				widthChange:$.Callbacks(),
				dataHandler:$.Callbacks(),
				setEditor:$.Callbacks(),
				scrollX:$.Callbacks(),
				scrollY:$.Callbacks()
    		});
			return this;
    	},
    	/** @description 初始化样式设置
    	 * 	@param {Object} grid igrid对象
   		 *  @param {Object} op igrid的参数设置
   		 */
    	initStyle: function(grid, op) {
    		op.width && grid.dom.width(op.width);
	        grid.dom.addClass('ccay-igrid').data('op', op);
	        //百分比显示模式
	        if(op.percentWidth){
	        	grid.dom.addClass('ccay-igrid-percent');
	        	op.wrap = op.wrap !== false ? true : false;
	        	
	        	op.allowFreezen = null;
	        	op.handler.afterBindData.add(this.fixScroll);
	        }
			//设置折行模式
	        op.wrap && grid.dom.addClass('ccay-igrid-wrap');
	        op.wrapWord && grid.dom.addClass("ccay-igrid-wrapword");
	        op.wrapHead && grid.dom.addClass('ccay-igrid-wraphead');
	        return this;
    	},
    	initColumnMap : function(grid, op){
			op._columnMap = {};
			if (op.columns && op.columns.length) {
				$.each(op.columns, function (i, col) {
					col.field && (op._columnMap[col.field] = col);
				});
			}
		},
		initConnectMap:function(grid,op){
			op._connectMap = {};
			if (op.columns && op.columns.length) {
				$.each(op.columns, function (i, col) {
					if(col.editorOp && col.editorOp.id){
						!op._connectMap[col.editorOp.id] && (op._connectMap[col.editorOp.id]={});
						op._connectMap[col.editorOp.id].self = col;
					}
					if(col.editorOp && col.editorOp.conf && col.editorOp.conf.connector){
						var connector = col.editorOp.conf.connector;
						if(typeof connector == "string"){
							var connectId = connector.substring(1);
							!op._connectMap[connectId] && (op._connectMap[connectId]={});
							!op._connectMap[connectId].child && (op._connectMap[connectId].child=[]);
							op._connectMap[connectId].child.push(col);
						}else{
							$.each(connector,function(i,n){
								var connectId = n.target.substring(1);
								!op._connectMap[connectId] && (op._connectMap[connectId]={});
								!op._connectMap[connectId].child && (op._connectMap[connectId].child=[]);
								op._connectMap[connectId].child.push(col);
							});
						}
					}
				});
			}
		},
    	/** @description 修正滚动条
    	 * 	@param {Object} grid igrid对象
   		 *  @param {Object} op igrid的参数设置
   		 */
    	fixScroll: function (grid, op) {
    		var showScroll = grid.getBodyPanel().height() < grid.getBodyTable().outerHeight(),
    			head = grid.getHeadTable();
    		head.parent().css('padding-right',showScroll ? '17px' : '');
    	},
    	/** @description 解析排序设置
    	 * 	@param {Object} grid igrid对象
   		 *  @param {Object} op igrid的参数设置
   		 */
    	parseSortSetting: function (grid, op) {
    		if (op.allowSort && op.remoteSort){
    			var sortArray = op._sortSetting && op._sortSetting.sort;
	    		// 当排序设置存在，并且是服务端排序时，则进行解析，否则返回默认设置中的排序
	    		if (op._sortSetting && op._sortSetting.isRemoteSort && sortArray) {
	    			var tempOrderBy = [], tempOrder;
	    			// 遍历排序数组，默认排序字段按照升序排序
	    			$.each(sortArray, function (sIdx, sortField) {
	    				if (sortField.field) {
	    					tempOrder = sortField.field + (sortField.sort === "desc" ? " desc" : " asc"); 
	    					tempOrderBy.push(tempOrder);
	    				}
	    			});
	    			// 将数组转成字符串
	    			return tempOrderBy.join(",");
	    		}
	    		return op.sort;
    		}
    	},
    	fixScrollToFullScreen: function (grid) {
    		var contentWidth = grid.getContent().width(),
    			scrollerWidth = grid.getScroller().children().width();
    		if (contentWidth > scrollerWidth) {
    			grid.syncScroll(0);
    		}
    	}
    }

	// 事件注册
    factory.EventBinder = {
        init: function (grid, op) {
        	this.bindScroll(grid);
            this.bindResize(grid, op);
            this.bindClick(grid, op);
        },
        bindScroll: function (grid) {
        	//阻止滚动冒泡
        	/*var panel = grid.getBodyPanel().bind("mousewheel",function(e){
	        	var panel = $(this),scrollTop = panel.scrollTop(),
	        		detail = e.originalEvent.wheelDelta,
	        		height = panel.children().height() -  panel.height();

	        	if(height > 0)
	        	{
	        		if(detail > 0 && scrollTop <= 0)
	        			return false;
	        		
	        		if(detail < 0 && scrollTop >= height)
	        		{
	        			Ccay.Core.log([scrollTop,height]);
	        			return false;
	        		}
	        	}
	        })*/
        	//非百分比模式下滚动事件(横向)注册
        	if(!grid.op.percentWidth)
        	{
	        	grid.getScroller().show().mousedown(function(){
	        		if(grid.op.validScroller == false) {
	        			 grid.endEdit();
	        		}
	        	}).scroll(function (e) {
	        			var scroller = $(this);
	        			//Ccay.Core.log("scroller:" + grid.op._noScroll);
	        			if(grid.op._noScroll)
	        			{
	        				setTimeout(function(){
	        					grid.op._noScroll = null;
	        				},10);
	        			}
	        			else
		            		grid.scrollX(scroller);
		        });
		        grid.getBodyPanel().scroll(function(){
		        	var panel = $(this),left = panel.scrollLeft(),op = grid.op;
		        	//Ccay.Core.log(grid.op._noScroll);
		        	if(left > 0)
		        	{
		        		if(!op.columnLazyLoad && !op._noScroll && !op._inEdit)
		        		{
		        			var scroller = grid.getScroller();
		        			grid.scrollX(scroller,left + scroller.scrollLeft());
		        		}
		        		else if(op._activeTd)
		        		{
		        			var col = grid.getColumnOp(op._activeTd);
		        			grid.scrollTo(col);
		        		}
		        		panel.scrollLeft(0);
		        	}
		        });
		        //修复使用Ctrl+F查找时igrid的列名和列值对应不一致
		        grid.getHeadPanel().scroll(function(){
                    grid.getBodyPanel().scrollLeft($(this).scrollLeft());
                    $(this).scrollLeft(0);
                });
        	}
        },
        bindResize: function (grid, op) {
			$.browser.msie && grid.dom.resize(function(e){
				grid.updateStyle(1);
				//.syncScroll(0);
			});
        },
        bindClick: function (grid, op) {
        	if(op.handler.click.length)
        		// 单元格点击事件注册
	            grid.getContent().delegate('[eno]', "click", function (e) {
	                var target = $(this), eNo = target.attr("eno"), isExecEno;
	                if (target.hasClass("grid-cell")) {
	                	var col = grid.getColumnOp(target), tr = grid.getCellRow(target);
	                	if(!op.onCellClick || op.onCellClick.call(grid, grid.cellData(target), grid.getRowData(tr) , target, tr, col._i, grid.getRowIndex(tr), col, grid, e) !== false) {
	                		// 设置表头点击事件
		                	if (target.parent().parent().hasClass("igrid-head")) {
		                		op.onHeadClick && op.onHeadClick.call(grid, e, target, col, grid);
		                	}
		                	isExecEno = true;
	                	}
	                } else {
	                	isExecEno = true;
	                }
	                if (isExecEno) {
	                	if(!op._disabled && (!op._readonly || eNo != "edit") && eNo && !target.hasClass('disabled')) {
		                	var trigger = op.handler.click.get(eNo);
			                trigger && trigger(e, target, grid);
	                	}
	                }
	            });
            // 设置触发行点击事件
            grid.getBodyTable().delegate("tr.grid-row", "click", function(e) {
            	var tr = $(this), td = $(e.target), col = grid.getColumnOp(td);
            	op.onRowClick && op.onRowClick.call(grid, grid.cellData(td), grid.getRowData(tr), td, tr, col._i, grid.getRowIndex(tr), col, grid, e);
            	if(!op._disabled && !tr.hasClass('igrid-actived') && !tr.hasClass('row-noselect'))
            	{
	            	if (op._hTr) {
	            		op._hTr.removeClass('igrid-actived');
	            		// 移除上一行的鼠标标示
	            		op._hTr.removeData("focusin");
	            	}
	            	tr.addClass('igrid-actived');
	            	op._hTr = tr;
            	}
            });
            // 设置mouseover事件
            grid.getBodyTable().delegate("td.grid-cell", "mouseover", function (e) {
            	var td = $(this), col = grid.getColumnOp(td), tr = grid.getCellRow(td);
            	op.onMouseOver && op.onMouseOver.call(grid, grid.cellData(td), grid.getRowData(tr), td, tr, col._i, grid.getRowIndex(tr), col, grid, e);
            });
        }
    }
    // 自定义对象
    factory.Custom = {
    	Table: {
    		buildHead: function (html, op, grid) {
            	html.push("<div class='ccay-igrid-head'><div class='ccay-igrid-headplace'>",
            		"<div id='" + grid.id + "Header' class='ccay-igrid-thead unselect igrid-itable-custom'></div></div></div>");
        	},
        	buildBody: function (html, op, grid) {
	            html.push("<div class='ccay-igrid-body'");
	            if (op.height || op.minHeight || op.maxHeight) {
	            	html.push(" style='");
	            	op.height && html.push("height:" + (isNaN(op.height) ? op.height : op.height) + "px", ";");
	            	op.minHeight && html.push("min-height:" + (isNaN(op.minHeight) ? op.minHeight : op.minHeight) + "px", ";");
	            	op.maxHeight && html.push("max-height:" + (isNaN(op.maxHeight) ? op.maxHeight : op.maxHeight) + "px", ";");
	            	html.push("'");
	            }  
	            html.push("><div class='ccay-igrid-bodyplace'><table id='" + grid.id + "Table' class='ccay-igrid-tbody igrid-itable-custom");
	            html.push("'><tbody class='igrid-colset'><tr><td style='width: 100%;' class='grid-cell'><div></div></td></tr></tbody>");
	            html.push("<tbody class='igrid-data ", op.contentCss || "","'></tbody></table></div>");
	            html.push("</div>");
	        }
    	},
    	Column: {
    		bulidRowForm: function () {
				var tempTmpl = ["<div>", "<div class='igrid-seq'></div>", "<div class='igrid-select'></div>", "<div class='igrid-icon'></div>"];
				tempTmpl.push("<div class='igrid-columns'><ul><li class='igrid-column'><samp class='igrid-title'></samp><span class='igrid-literal'></span></li>");
				tempTmpl.push("</ul></div></div>");
				return tempTmpl.join("");
			},
    		//设置表头单元格html
	        setHeadHtml: function (grid, col, html) {
	            html.push("<li");
	            IGrid.Helper.addProp(html,col.headAttr);
	            html.push("><div class='igrid-innercell'");
	            html.push(">", col.headHtml, "</div></li>");
	        	return this;
	        },
    		 //单元格模板
			setTmpl: function (col, tmplObj, colTmpl, tempDom) {
				if (!col.content && !col._renderTd)
					col.content = col.field ? "${" + col.field + "}" : "";
				if (tempDom[col._module].length) {
					// 设置内容
					if (col.inner) {
						// 设置属性
						col.cssName && tempDom[col._module].addClass("${cssName}");
						tempDom[col._module].attr("eno", "${eNo}").text("${content}");
						tmplObj[col._module] = tempDom[col._module][0].outerHTML.formatField(col, "non");
					} else {
						var tempModule = tempDom[col._module].clone(),
							tempAttr = {"_col": "${attr._col}", "field": "${field}", "eno": "${eNo}"};
						if (col.valueField) {
							tempAttr["valueField"] = "${valueField}";
							tempAttr["val"] = "${attr.val}"
						}
						tempModule.find(".igrid-title").addClass("${attr._required}").text("${header}");
						tempModule.find(".igrid-literal").addClass("${attr.class}").attr(tempAttr).text("${content}");
						colTmpl.push(tempModule[0].outerHTML.formatField(col, "non"));
					}
				}
				return this;
	        },
	        buildHead: function (grid, headHtml, selectHtml) {
	            grid.getHeadTable().html("<div class='igrid-head-operate'>" + selectHtml.join('') + "</div><div class='igrid-head-content'><ul>" + headHtml.join('') + "</ul></div>");
	        },
	        buildRow:function(grid, op, tmpl){
	        	op.rowAttr._row || (op.rowAttr._row = "${#data._newIndex || _rowNo}");
	        	op.rowCodeBegin.push("data.rowIdx = _rowNo;")
	        	var row = [];
	        	op.rowCodeBegin.length && row.push("<% ",op.rowCodeBegin.join(""), " %>");
	        	row.push("<tr class='", op.rowClass.join(" "), "${#index%2 ? '' : ' odd'}${#Ccay.UI.IGrid.Helper.setRowStatus(data)}'");
	        	IGrid.Helper.addProp(row,op.rowAttr);
	        	row.push("><td class='grid-cell-custom'>", tmpl, "</td></tr>");
	        	op.rowCodeEnd.length && row.push("<% ",op.rowCodeEnd.join(""), " %>");
	        	op.tmpl = row.join('');
	        	op.handler.changeTmpl && op.handler.changeTmpl.fire(grid, op, tmpl);
	        	
	        }
    	}
    };
    // 通用对象
    factory.Common = {
    	Table: {
    		init: function (op, html, grid) {
	            this.buildHead(html, op, grid);
	            this.buildBody(html, op, grid);
	            this.buildFoot(html);
	        },
	        buildHead: function (html, op, grid) {
	            html.push("<div class='ccay-igrid-head'><div class='ccay-igrid-headplace'>",
	            		"<table id='" + grid.id + "Header' class='ccay-igrid-thead unselect igrid-itable'></table></div></div>");
	        },
	        buildBody: function (html, op, grid) {
	            html.push("<div class='ccay-igrid-body'");
	            if (op.height || op.minHeight || op.maxHeight) {
	            	html.push(" style='");
	            	op.height && html.push("height:" + (isNaN(op.height) ? op.height : op.height) + "px", ";");
	            	op.minHeight && html.push("min-height:" + (isNaN(op.minHeight) ? op.minHeight : op.minHeight) + "px", ";");
	            	op.maxHeight && html.push("max-height:" + (isNaN(op.maxHeight) ? op.maxHeight : op.maxHeight) + "px", ";");
	            	html.push("'");
	            }  
	            html.push("><div class='ccay-igrid-bodyplace'><table id='" + grid.id + "Table' class='ccay-igrid-tbody igrid-itable");
	            html.push("'><tbody class='igrid-colset'></tbody><tbody class='igrid-data'></tbody></table></div>");
	            html.push("</div>");
	        },
	        buildFoot: function (html) {}
    	},
    	Column: {
    		/** @description 初始化列设置
	    	 * 	@param {Object} grid igrid对象
	   		 *  @param {Object} op igrid的参数设置
	   		 */
	        init: function (grid, op) {
	            if (op.columns && op.columns.length) {
	            	op._dateFields = [];
					op._mappingFields = [];
	            	// 百分比模式下，设置列宽
	            	op.percentWidth && this.percentInit(grid, op);
	                for (var i = 0, col; col = op.columns[i]; i++) {
	                    // 初始化列头属性
	                    col.headAttr || (col.headAttr = {});
	                    // 初始化列属性
	                    col.attr || (col.attr = {});
	                    // 设置默认事件
	                    col.headENo = col.eNo = "cellClick";
	                    // 设置列索引
	                    col._i = col.headAttr["_col"] = col.attr["_col"] = i;
	                    // 设置表头样式
	                    col._headCss = col.headCss || "";
	                    // 设置列样式
	                    col.cssName == null && (col.cssName = "");
	                    // 触发列设置的代理
	                    op.handler.setColumn.fire(grid, col, op);
	                    // 触发列编辑器设置
	                    op.handler.setEditor.fire(grid, col, op);
	                    //设定列标示
	                	col._ctype || (col._ctype = col.field);
	                	// 设置列模块
	        			col._module || (col._module = "igrid-column");
	        			// 不是内置列的列样式添加更新标示的方法判断
	        			!col.inner && (col.cssName += " ${#Ccay.UI.IGrid.Helper.setCellUpdated(data, '{0}')}".formatValue(col.field));
	                }
	               	this.buildCol(grid,op);
	        	}
	        },
	        percentInit: function (grid, op) {
	        	var totalWidth = 0, curWidth;
	        	// 遍历获取非隐藏列的宽度
	        	$.each(op.columns, function (colIndex, col) {
	        	 	if (!col.hidden) {
	        	 		curWidth = parseInt(col.width) || 0;
	        	 		totalWidth += curWidth;
	        	 	}
	        	});
	        	// 若总宽度不是100时，将多余的比例均分到每一列上，再保存个性化
	        	if (totalWidth != 100) {
	        		// 遍历列，重新设置列宽度
	        		$.each(op.columns, function (colIndex, col) {
		        	 	if (!col.hidden && !col.inner && !col.columnType) {
		        	 		curWidth = parseInt(col.width) || 0;
		        	 		col.width = (curWidth * 100 / totalWidth) + "%";
		        	 	}
		        	});
	        	}
	        },
	        /** @description 生成列
	    	 * 	@param {Object} grid igrid对象
	   		 *  @param {Object} op igrid的参数设置
	   		 */
	        buildCol:function(grid, op){
	        	var columns = op.columns, helper = Ccay.DataHelper, headHtml = [], tmpl = [];
	        	if (op.customTable) {
	        		var customDom, tempDom, tmplObj = {}, colTmpl = [], selectHtml = [];
	        		// 解析模板
	        		op.customTmpl || (op.customTmpl = this.bulidRowForm());
	        		customDom = $(op.customTmpl);
	        		// 获取自定义模板的4个模块
	        		tempDom = {
	        			"igrid-seq": customDom.find(".igrid-seq"),
	        			"igrid-select": customDom.find(".igrid-select"),
	        			"igrid-icon": customDom.find(".igrid-icon"),
	        			"igrid-column": customDom.find(".igrid-column")
	        		};
	        		// 将4个模块使用占位符替换
	        		for (var tType in tempDom) {
	        			tempDom[tType].replaceWith("${" + tType + "}");
	        		}
	        		// 创建4个模块的模板
	        		for (var i = 0, col; col = columns[i]; i++) {
	                	if (!col.hidden) {
	                		col._indexCss = grid.id + "-col" + col._i;
	                		this.setColAttr(col, grid);
	                		// 表头全选模板
	                		if (col.multi) {
	                			selectHtml.push("<div");
					            IGrid.Helper.addProp(selectHtml,col.headAttr);
					            selectHtml.push("><div class='igrid-innercell'><span></span></div></div>");
	                		} else if (!col.inner && col.field) {
	                			this.setHeadHtml(grid, col, headHtml);
	                		}
	                		this.setTmpl(col, tmplObj, colTmpl, tempDom);
	                	}
	        		}
	        		tmplObj["igrid-column"] = colTmpl.join("");
	        		this.buildHead(grid, headHtml, selectHtml);
		           	this.buildRow(grid, op, customDom.html().formatText(tmplObj));
	        	} else {
		    		var fzTmpl = [], fzHeadHtml = [], colSet = [], fzColSet = [],
						fzNum = 0, colNum = 0, fzColWidth = 0, colWidth = 0;
	            	for (var i = 0, col; col = columns[i]; i++) {
		                if (!col.hidden) {
		                	col._curWidth = parseInt(col.width) || 0;
			                if (op.allowFreezen && col.freezeable  && (!op.fzNum || (op.fzNum && fzNum<=op.fzNum))) {
			                	//累计锁定列的宽度
			                	fzColWidth += col._curWidth;
			                	col._curIndex = fzNum++;
			                	col._indexCss = grid.id + "-fzcol" + col._curIndex;
			                	this.setColAttr(col, grid);
			                	op.columnLazyLoad || this.buildColHtml(grid, col, fzTmpl, fzHeadHtml, fzColSet);
			                } else {
			                	colWidth += col._curWidth;
			                	col._curIndex = colNum++;
			                	col._indexCss = grid.id + "-col" + col._curIndex;
			                	this.setColAttr(col, grid);
			                	op.columnLazyLoad || this.buildColHtml(grid, col, tmpl, headHtml, colSet);
			                }
		                }
	            	}
		            if (!op.percentWidth) {
			            op._colSet = {
			            	count:colNum,
			            	width:colWidth
			            };
			            op._fzColSet = {
			            	count:fzNum,
			            	width:fzColWidth
			            };
			            op.fzNum = fzNum;
		            }
		            if (!op.columnLazyLoad)  {
			           	this.buildRow(grid,op, tmpl, fzTmpl);
			           	this.buildHead(grid, headHtml,fzHeadHtml,colSet,fzColSet);
		            }
	            	op.columnLazyLoad && grid.initScrollLoadColumn(0);
	            	this.buildXScroll(grid,op);
	        	}
	        	// 存在时间字段就进行转换
	            if (op._dateFields.length) {
	            	op.handler.dataHandler.add(function (record, grid, op, data) {
                		$.each(op._dateFields, function (index, dateField) {
                			var oriDate = helper.getObj(dateField.field, record),
                				changeDate = Ccay.Format.toDate(oriDate, dateField.type);
                			helper.setObj(dateField.field, record, changeDate);
                		});
	            	});
	            }
	            // 存在映射字段就进行添加
	            if (op._mappingFields.length) {
	            	op.handler.dataHandler.add(function (record, grid, op, data) {
                		$.each(op._mappingFields, function (index, mappingField) {
                			record[mappingField.field] = mappingField.func(helper.getObj(mappingField.funcParam, record), record);
                		});
	            	});
	            }
	        },
	        buildRow:function(grid, op, tmpl, fzTmpl){
	        	op.rowAttr._row || (op.rowAttr._row = "${#data._newIndex || _rowNo}");
	        	op.rowCodeBegin.push("data.rowIdx = _rowNo;")
	        	var row = [];
	        	op.rowCodeBegin.length && row.push("<% ",op.rowCodeBegin.join(""), " %>");
	        	row.push("<tr class='", op.rowClass.join(" "), "${#index%2 ? '' : ' odd'}${#Ccay.UI.IGrid.Helper.setRowStatus(data)}'");
	        	IGrid.Helper.addProp(row,op.rowAttr);
	        	row.push(">",fzTmpl.join(""),tmpl.join(""),"</tr>");
	        	op.rowCodeEnd.length && row.push("<% ",op.rowCodeEnd.join(""), " %>");
	        	op.tmpl = row.join('');
	        	op.handler.changeTmpl && op.handler.changeTmpl.fire(grid, op, tmpl, fzTmpl);
	        	
	        },
	        buildHead: function (grid, headHtml,fzHeadHtml,colSet,fzColSet) {
	            var trColSet = "<tr>" + fzColSet.join('') + colSet.join(''),
	            	setPanel = grid.getColSet().html(trColSet + "</tr>"),
	            	td = setPanel.children().children(':first');
	            	//计算列宽的修正值
	            	if(!grid.op.percentWidth)
	            		grid.op._colSet.fixed = td.outerWidth() - td.width();
	
	            grid.getHeadTable().html("<tbody class='igrid-colset'>" + trColSet + "</tr></tbody><tbody class='igrid-head'><tr>" + fzHeadHtml.join('') + headHtml.join('') + "</tr></tbody>");
	        },
	        buildXScroll:function(grid,op){
	        	if(!op.percentWidth){
	        		op.handler.widthChange.add(this.setScrollWidth);
	        		this.setScrollWidth(grid);
	        	}
	        },
	        /** @description 设置滚动的宽度
	    	 * 	@param {Object} grid igrid对象
	   		 */
	        setScrollWidth:function(grid){
	        	var colSet = grid.op._colSet,fzColSet = grid.op._fzColSet,
	    		width = fzColSet.width + colSet.width + colSet.fixed * (colSet.count + fzColSet.count);
				grid.getScroller().children().width(width);
				// 修正滚动条的位置
				factory.fixScrollToFullScreen(grid);
	        },
	         /** @description 设置列属性
	          *  @param {Object} col 列设置
	    	  *  @param {Object} grid igrid对象
	   		  */
	        setColAttr : function (col, grid) {
	        	col.field && (col.headAttr["field"] = col.attr["field"] = col.field);
	        	if (col.valueField) {
	        		col.headAttr["valueField"] = col.attr["valueField"] = col.valueField;
	        		col.attr["val"] = "${#Ccay.DataHelper.getObj('" + col.valueField + "', data)}";
	        	}
	        	//设置列事件编码
	        	col.headAttr["eno"] = col.headENo;
	        	col.attr["eno"] = col.eNo;
	        	//列样式设置
	        	col.headAttr["class"] = "grid-cell " + col._indexCss + " " + col._headCss;
	        	col.attr["class"] = "grid-cell " + col._indexCss + " " + (col.cssName || '');
	        	return this;
	        },
	        buildColHtml:function(grid,col,tmpl,html,colSet){
	        	this.setHeadHtml(grid,col,html,colSet);
	        	this.setTmpl(col,tmpl);
	        },
	        //单元格模板
			setTmpl: function (col,tmpl) {
	        	if (!col.content && !col._renderTd)
	                col.content = col.field ? "${" + col.field + "}" : "";
	            tmpl.push("<td");
				IGrid.Helper.addProp(tmpl,col.attr);
	            tmpl.push(">", col.content, "</td>");
	            return this;
	        },
	        //设置表头单元格html
	        setHeadHtml: function (grid,col,html,colSet) {
	        	var width =" style='width:" + (grid.op.percentWidth ?  Ccay.Format.getPixe(col.width) : (col._curWidth + "px")) + ";'";
	            html.push("<td");
	            IGrid.Helper.addProp(html,col.headAttr);
	            html.push("><div class='igrid-innercell'");
	            html.push(">", col.headHtml, "</div></td>");
	            //设置默认列宽
	            colSet.push("<td class='grid-cell ",col._indexCss,"'",width,"><div></div></td>");
	        	return this;
	        }
    	}
    };
    // 列设置对象
    factory.Column = {};
    // table生成器
    factory.Table = {};
	//结构构造器
    factory.Builder = {
        init: function (grid, op) {
            var html = [];
            this.buildToolbar(html, op);
            this.buildCentent(html, op, grid);
            this.buildButtom(html, op);
            grid.dom.html(html.join(''));
        },
        buildToolbar: function (html, op) {
            html.push("<div class='ccay-igrid-top'><div class='ccay-igrid-style'><div class='ccay-igrid-colstyle' /></div></div>");
        },
        buildCentent: function (html, op, grid) {
            html.push("<div class='ccay-igrid-content'>");
             if (op.customTable) {
            	$.extend(factory.Table, factory.Common.Table, factory.Custom.Table);
            } else {
            	factory.Table = $.extend({}, factory.Common.Table);
            }
            factory.Table.init(op, html, grid);
            // ie8浏览器下，customTable模式存在igrid-scroller时，错误信息提示不出来
            (!op.percentWidth && !op.customTable) && html.push("<div class='igrid-scroller'><div class='igrid-scroller-x'></div></div>");
            html.push("</div>");
        },
        buildButtom: function (html, op) {
            html.push("<div class='ccay-igrid-bottom'></div>");
        }
    };
    
    var manager = {
    	/**
         * 
         * @description	设置列是否冻结
    	 * @param field 列名	{String}
    	 * @param isFreeze 是否冻结{boolean} 默认false
         */
        setFreeze:function(field,isFreeze){
         if(!field){
        	return ;
        }
        isFreeze = !isFreeze?false:true;
        var temp = this.op.columns;
        var index = 0;
        $.each(temp,function(i,d){
        if(field == d.field){
        	index = i;
        } 
        });
        if(index == 0){
            return;
        }
        this.op.columns[index].freezeable=isFreeze;
        this.reInit(this.op);
        },	
		/**
		 * @description更新无数据记录时提示信息
		 * @param info 提示信息
		 */
		setNoResult:function(info){
			this.getBodyPanel().find(".grid-no-result").text(info);
			return this;
		},
		/** @description 获取grid头部容器
	     *  @return {JQDom}
	     */
		getHead: function () 
		{
	        return DomClass.getProp(this, this.dom, 'head', '.ccay-igrid-top');
	    },
	    /** @description 获取grid中部容器
	     *  @return {JQDom}
	     */
		getContent: function () 
		{
            return DomClass.getProp(this, this.dom, "content", ".ccay-igrid-content");
        },
        /** @description 获取grid底部容器
	     *  @return {JQDom}
	     */
        getBottom: function ()
        {
	        return DomClass.getProp(this, this.dom, 'bottom', '.ccay-igrid-bottom');
	    },
	    /** @description 获取grid的工具栏
	     *  @return {JQDom}
	     */
	    getMiniToolBar: function () 
	    {
	    	var toolPanel = this.op.toolPanel,
	    		container = toolPanel ? $(toolPanel) : this.getContent();
	    	return DomClass.getProp(this, container, "minitoolbar", ".igrid-minitoolbar");
	    },
	    /** @description 获取grid头部的样式容器
	     *  @return {JQDom}
	     */
	    getStylePanel: function ()
	    {
            return DomClass.getProp(this, this.getHead(), "pStyle", ".ccay-igrid-style");
        },
        /** @description 获取grid头部的列样式容器
	     *  @return {JQDom}
	     */
        getColStylePanel: function ()
        {
            return DomClass.getProp(this, this.getStylePanel(), "colStyle", ".ccay-igrid-colstyle");
        },
        /** @description 获取grid中部的表头div容器
	     *  @return {JQDom}
	     */
        getHeadPanel: function ()
        {
            return DomClass.getProp(this, this.getContent(), "phead", ".ccay-igrid-head");
        },
        /** @description 获取grid中部的内容容器
	     *  @return {JQDom}
	     */
        getBodyPanel: function ()
        {
            return DomClass.getProp(this, this.getContent(), "pbody", ".ccay-igrid-body");
        },
        /** @description 获取grid中部的表头table容器
	     *  @return {JQDom}
	     */
        getHeadTable: function ()
        {
            return DomClass.getProp(this, this.getHeadPanel().children(), "thead", ".ccay-igrid-thead");
        },
        /** @description 获取grid中部的表内容div容器
	     *  @return {JQDom}
	     */
        getBodyPlace: function ()
        {
            return DomClass.getProp(this, this.getBodyPanel(), "bodyplace", ".ccay-igrid-bodyplace");
        },
        /** @description 获取grid中部的表内容table容器
	     *  @return {JQDom}
	     */
        getBodyTable: function ()
        {
            return DomClass.getProp(this, this.getBodyPlace(), "tbody", ".ccay-igrid-tbody");
        },
        /** @description 获取grid中部的表内容tbody容器
	     *  @return {JQDom}
	     */
        getDataBody: function ()
        {
            return DomClass.getProp(this, this.getBodyTable(), "dataBody", ".igrid-data");
        },
        /** @description 获取grid中部的列设置容器
	     *  @param {Boolean} isHead 是否是表头
	     * 					true：获取grid中部的表头table的列设置容器
	     * 					false：获取grid中部的表内容table的列设置容器
	     *  @return {JQDom}
	     */
        getColSet: function (isHead)
        {
            return DomClass.getProp(this, isHead ? this.getHeadTable() : this.getBodyTable(), isHead ? "pHColSet" : "pColSet", ".igrid-colset");
        },
        /** @description 获取grid中部的滚动条容器
	     *  @return {JQDom}
	     */
        getScroller: function ()
        {
            return DomClass.getProp(this, this.getContent(), "pScroller", ".igrid-scroller");
        },
        refreshScroller:function(){
        	if(this.op.allowFreezen || !this.op.percentWidth)
	    	{
	    		var scroller = this.getScroller(),head = this.getColSet(true);
	        	scroller.children().width(head.outerWidth());
	    	}
        },
        /** @description 更新样式
	     *  @param {Boolean} isInit 是否是初始化
	     *  @return {IGrid}
	     */
        updateStyle: function (isInit)
        {
        	//是否初始化
    		if (isInit)
    		{
    			//this.refreshScroller();
    		}
    		else 
    		{
    			//设置序号列
	    		if (!this.op.percentWidth && this.op.showSeq && this.op.serialSeq)
	        	{
	        		var seqTd = this.getDataBody().children('tr:last').children('td:first'),
	        			seqWidth = seqTd.children().width();
	        		seqWidth > seqTd.width() && this.setColWidth(seqTd,seqWidth + 2);
	        	}
    		}
        	return this;
        },
        /** @description 设置单元格所在列的宽度
	     *  @param {JQDom} cell 单元格对象
	     *  @param {String} width 宽度
	     *  @return {IGrid}
	     */
        setColWidth: function (cell, width)
        {
        	var grid = this,op = grid.op,col = grid.getColumnOp(cell),filter
        		colSet = col.freezeable && op.allowFreezen ? op._fzColSet : op._colSet,
        		widthPanel = grid.getColSet(),headWidthPanel = grid.getColSet(true);
        	//百分比模式下会重新计算各列宽度
        	if(op.percentWidth && !col.inner)
        	{
        		var totalWidth = grid.getBodyTable().width(),
        			fixed,minWidth,colWidth,total = 0,
        			//百分比模式下的最小宽度
        			minWidth = 5000 / totalWidth,remain = 0;
        				
        		width = width / totalWidth * 100;
        		//最小宽度判断
        		width < minWidth && (width = minWidth);
				//每列宽度变化的的平均值
        		fixed = (parseFloat(col._curWidth) - width) / (op._resizeColNum - 1);

        		//设置可改变大小各列
        		$.each(op.columns,function(i,column){
        			if(col._i != column._i && !column.hidden)
        			{
        				colWidth = parseFloat(column._curWidth);
        				if(column.resizable || (!column.inner && !column.columnType && column.resizable !== false))
        				{
        					colWidth = colWidth + fixed;
        					//如果是其他列缩小模式下，做最小宽度的处理
        					if(fixed < 0)
        					{
        						if(colWidth < minWidth)
	        					{
	        						remain += minWidth - colWidth;
	        						colWidth = minWidth;
	        					}
	        					else
	        					{
	        						//判断余留
		        					if(remain > 0)
		        					{
		        						
		        						if(colWidth - remain >= minWidth)
		        						{
		        							colWidth += remain;
		        							remain = 0;
		        						}
		        						else
		        						{
		        							remain += minWidth - colWidth + remain;
		        							colWidth = minWidth;
		        						}
		        					}
	        					}
        					}
        					column._curWidth = colWidth + '%';
        					filter = '> tr > td.' + column._indexCss;
        					//设置列宽
				        	grid.getColSet().find(filter).width(column._curWidth);
				        	//设置表头列宽
				        	grid.getColSet(true).find(filter).width(column._curWidth);
        				}
        				total += colWidth
        			}
        		});
				//计算剩余值
        		width = (100 - total) + '%';
        	}

        	filter = '> tr > td.' + col._indexCss;
        	//设置列宽
        	grid.getColSet().find(filter).width(width);
        	//设置表头列宽
        	grid.getColSet(true).find(filter).width(width);

        	if(!op.percentWidth)
	        	//修正总宽度
	        	colSet.width += width - col._curWidth;

        	//触发列宽改变事件
        	grid.op.handler.widthChange && grid.op.handler.widthChange.fire(grid,width,col, cell);
        	
	        col._curWidth = col.width = width;
	        //修复ie8 下拖拽列宽后，选择的checkbox 或radio样式错乱问题，强制刷新span，让其居中
	        grid.dom.find("td.grid-select span").text("");
        	return grid;
        },
        /** @description 获取单元格所在列的索引
         *  @param {JQDom} cell 单元格对象
         *  @return {Number}
         */
	    getColumnIndex: function (cell)
	    {
	        // var td = cell[0].tagName == 'TD' ? cell : cell.parents("td:first");
	    	var td = cell.hasClass("grid-cell") ? cell : cell.parents("td:first");
	        return td.length ? td.attr('_col') * 1: -1;
	    },
	    /** @description 获取单元格所在行对象
         *  @param {JQDom} cell 单元格对象
         *  @return {JQDom}
         */
	    getCellRow: function (cell)
	    {
	    	//return cell[0].tagName != "TR"  ? cell.parents('tr:first') : cell;
	    	var row = cell;
	    	if(cell.length){
	    		row = (cell[0].tagName != "TR")  ? cell.parents('tr:first') : cell
	    	}
	    	/*
	    	 * 存在场景，当前行渲染后，正在编辑td获取不到对应的行
	    	 * 那么就在获取当前编辑的行
	    	 */
	    	!row.length && this.op._activeEditTr!=null && (row = this.getRow(this.op._activeEditTr));
	    	return row;
	    },
	    isNewRow:function(row){
	    	return row.hasClass(IGrid.Const.inserted.css);
	    },
	    /** @description 获取单元格所在行的索引
         *  @param {JQDom} row 行对象
         *  @return {Number}
         */
	    getRowIndex: function (row)
	    {
	    	return this.getCellRow(row).attr('_row') * 1;	
	    },
	    getRowNo:function(row){
	    	var rowData = this.getRowData(row),
	    		pageInf = this.op.pagerOp.pageInf;
	    	if(rowData._index > -1)
		    	return (pageInf.curPage-1) * pageInf.pageSize + rowData._index;
	    	return -1;
	    },
	    /** @description 通过索引获取行对象
         *  @param {Number} index 索引
         *  @return {JQDom}
         */
	    getRow: function (index)
	    {
	    	return this.getBodyTable().children().children("tr[_row='" + index + "']:first");
	    },
	    getRowCell:function(row,columnIndex){
	    	row.jquery || (row = this.getRow(row)); 
	    	return row.find('[_col="' + columnIndex + '"]');
	    },
	    /** @description 获取单元格所在列的配置信息
         *  @param {JQDom} cell 单元格对象
         *  @return {}
         */
	    getColumnOp: function (cell)
	    {
	    	var index = (typeof(cell) == "number") ? cell : this.getColumnIndex(cell);
	        return index > -1 ? this.op.columns[index] : this.op.columns[0];
	    },
	    /** @description 获取行数据
         *  @param {JQDom} row 行对象
         *  @return {}
         */
	    getRowData: function (row)
	    {
	    	var index = (typeof(row) == "number") ? row : this.getRowIndex(row);
			if (index != null)
			{
				return this.op.Storage.at(index);
			}
	        return null;
	    },
	    /** @description 重置单元格数据
         *  @param {JQDom} td 列对象
         *  @param {String} value 值
         * 					为空：获取单元格数据
         * 					不为空：将值替换到单元格中，并获取整行数据集
         *  @param {Object} col 列的配置信息
         *  @return {}
         */
	    cellData: function (td, value, col)
	    {
	    	var field = this.getValueField(td.attr('field')), helper = Ccay.DataHelper;
	        if (field) {
	            var rowData = this.getRowData(td);
	            if (rowData) {
	            	//value为空获取行数据，不为空位赋值
	                if (value != null)
	                {
	                	//判断value是否为对象
	                	if ($.isPlainObject(value)) {
	                		col || (col = this.getColumnOp(td));
	                    	//判断是否同时有value和display两项属性
	                    	col.field != field && helper.setObj(col.field,rowData,helper.getObj("text", value));
	                		value = helper.getObj("value", value);
	                	} else {
	                		// 若不是渲染组件，则不需要转换数据类型，格式化值
	                		value = this.renderValue(td, col, value);
	                	}
	                	this.op.Storage.updateItem(rowData, field, value);
	                    return rowData;
	                } else {
	                    return helper.getObj(field, rowData);
	                }
	            }
	        }
	        return null;
	    },
	    /** @description 获取单元格显示的文本数据
         *  @param {JQDom} td 列对象
         *  @param {Object} col 列的配置信息
         *  @param {String} value 值
         * 					为空：获取单元格显示的文本数据
         * 					不为空：将值显示到单元格中
         *  @param {Boolean} updateData 是否将值替换到单元格
         *  @return {}
         */
	    cellValue: function (td, col, value, updateData, oldValue)
	    {
	    	/*
	    	 * 存在场景，当前行渲染后，正在编辑td获取不到对应的行
	    	 * 那么就在这里根据当前编辑的行获取对应的列
	    	 */
	    	if(!td.parent().length && this.op._activeEditTr!=null){
	    		 td = this.getRow(this.op._activeEditTr).children("td[_col='"+td.attr("_col")+"']");
	    	}
	    	var renderer = col.renderer;
	    	// value为空获取单元格数据，不为空为赋值
	    	if (value == null) {
	    		// 获取值
	    		return this.renderValue(td, col);
	    	} else {
	    		// 是否更新数据
	    		if (updateData) {
	    			// 格式化值
	    			value = this.renderValue(td, col, value);
	    			// 处理复制渲染值
		            var mapping = col.mappingRenderField, 
		            	rowData = this.getRowData(td), isRenderRow;
	    			// 执行编辑之后的委托方法，返回为true时重写渲染整行数据
	    			if (col.fnEndEdit && !this.op.fnEndEdit) {
		            	isRenderRow = col.fnEndEdit.call(this, value, rowData, td, col, oldValue);
		            } else if (!col.fnEndEdit && this.op.fnEndEdit) {
		            	isRenderRow = this.op.fnEndEdit.call(this, value, rowData, td, col, oldValue);
		            }
	    			if (isRenderRow !== false) {
	    				if (isRenderRow == true) {
	    					var field = this.getValueField(td.attr('field'));
		    				// 原始数据未改变，则进行单元格渲染赋值，否则，进行行渲染
	    					if (Ccay.DataHelper.getObj(field, rowData) != ($.isPlainObject(value) ? value.value : value)) {
	    						// 更新值
	    						rowData = this.cellData(td, value, col);
	    						// 重写渲染，若不是渲染组件，则调用用户自定义的渲染方法
	    						this.renderValue(td, col, value, true, rowData);
	    					}
		    				this.renderRow(td, rowData);
	    				} else {
	    					// 更新值
	    					rowData = this.cellData(td, value, col);
	    					// 重写渲染，若不是渲染组件，则调用用户自定义的渲染方法
		    				this.renderValue(td, col, value, true, rowData);
	    				}
	    				var curUTCTime = $.type(value) == "date" ? value.getUTCTime(8,Ccay.Personalized.global.common.timeZone) : value;
	    				curUTCTime !== value && col.field && (rowData[col.field] = curUTCTime);
	    				
	    				mapping && (rowData[mapping] = td.text());
	    				col.totalCount && this.totalColumn();
	    				this.clearConnectData(td, col);
	    				return rowData;
	    			} else {
	    				mapping && (rowData[mapping] = td.text());
	    				return false;
	    			}
	    		}
	    	}
	    },
	    
	     /** @description 针对单元格赋值
	     *  @param {number} 行索引
	     *  @param {String} field 名称
	     *  @return vallue
	     */
	    setTdValue:function(rowIndex,field,value){
	    	if($.type(field) == "string"){
		    	var grid = this,
		    		tr = grid.getRow(rowIndex);
		    	if(tr){
		    		var td = grid.getCellByField(rowIndex,field) ,
		    			rowData = grid.getRowData(tr),
		    			col = grid.getColumnOp(td),
		    			valueField = td.attr("valuefield"),
		    			oldValue = valueField ? { value:rowData[valueField] , text:rowData[field] } : rowData[field];
		    			
		    		if( Ccay.UI.IGrid.Editor.compareValue(value,"",col,grid,oldValue) ){
		    			return ;
		    		}
		    		
		    		if ($.isPlainObject(value)){
		    			rowData[valueField] = value.value;
		    			rowData[field] = value.text;
		    		}else {
		    			rowData[field] = value;
		    		}
		    		
	    			if(grid.validRecord(rowData) != false){
		    			if (grid.cellValue(td, col, value, true, oldValue) !== false) {
	                        if (!grid.isNewRow(tr)) {
	                        	td.addClass('cell-update');
	                        	tr.hasClass(Ccay.UI.IGrid.Const.updated.css) || tr.addClass(Ccay.UI.IGrid.Const.updated.css);
	                        }
	                    }
	    			}
		    	}
	    	}
	    },
	    /** @description 获取渲染后的行对象
	     *  @param {JQDom} td 列对象
	     *  @param {Object} data 值
	     *  @return {IGrid}
	     */
	    renderRow: function (td, data)
	    {
	    	var tr = this.getCellRow(td),
	    		index = this.getRowIndex(tr),
	    		tmpl = this.op.tmpl,
	    		tdRowspan = tr.children("td[rowspan]"),tdHidden=tr.children("td.hide");
	    	//修复igrid在行分组的时候使用行渲染出现的问题
	    	if(this.op.rowRender != "group"){
	    		tmpl = this.op.tmpl.substring(tmpl.indexOf('<td'),tmpl.lastIndexOf('td>') + 3);
	    	}else{
	    		tmpl = this.op.tmpl.substring(tmpl.lastIndexOf('<tr'),tmpl.lastIndexOf('tr>')+3);
	    		tmpl = tmpl.substring(tmpl.indexOf('<td'),tmpl.lastIndexOf('td>') + 3);
	    	}
	    	tr.html(Ccay.UI.template("<% with(data){ %>"+ tmpl + " <% } %>",{data:data}, index + 1, null, {_grid: this}, true));
	    	/**
	    	 * 修复在场景行合并过程中，编辑结束调用行渲染事件会出现igrid列变形
	    	 * tdRowspan：考虑多行情况
	    	 * tdHidden：考虑隐藏的列(除设置为隐藏的列，也包含前面存在多行，导致该列隐藏)
	    	 */
	    	tdRowspan.each(function(){
	    		tr.children("td[_col='"+$(this).attr("_col")+"']").attr("rowspan",$(this).attr("rowspan"));
	    	});
	    	tdHidden.each(function(){
	    		tr.children("td[_col='"+$(this).attr("_col")+"']").addClass("hide");
	    	});
	    	return this;
	    },
	    getFocusRow:function(){
	    	var tr = this.getRows('tr.grid-row.igrid-actived:first');
	    	if(tr.length)
	    		this.op._hTr = tr;
	    	return tr;
	    },
	    setFocusRow:function(tr){
	    	this.op._hTr && this.op._hTr.removeClass('igrid-actived');
        	tr.addClass('igrid-actived');
        	this.op._hTr = tr;
	    },
	    /** @description 通过过滤器获取行对象
	     *  @param {String} filter 过滤器
	     *  @return {JQDom}
	     */
	    getRows: function (filter)
	    {
    		return this.getBodyTable().children().children(filter);
	    },
	    /** @description 获取选中的行对象
	     *  @param {Boolean} unSelected 是否没有选中
	     *  @param {String} filter 过滤器
	     *  @return {JQDom}
	     */
	    getSelectRows: function (unSelected, filter)
	    {
	    	filter = 'tr.grid-row' + (unSelected ? ":not(.row-noselect):not(." + IGrid.Const.selected.css + ")" : "." + IGrid.Const.selected.css) + (filter || '');	
    		return this.getRows(filter);
	    },
	    /** @description 模拟横向滚动
	     *  @param {JQDom} scroller 滚动条对象
	     *  @param {String} left 左边距
	     *  @return {IGrid}
	     */
	    scrollX: function (scroller, left,isTriggerEvent)
	    {
	    	var grid = this,op = grid.op,start = 0,scrollX = 0;
	    	if (left != null)
	    	{
	    		scroller.scrollLeft(left);
	    		if(isTriggerEvent){
	    			//设置不触发滚动事件
	    			op._noScroll = true;
	    		}
	    		else
	    			return;
	    	}
	    	else
	    	{
	    		left = scroller.scrollLeft();
	    	}
	    	
	    	if (left > 0)
	    	{
	    		var scrollX,num = 0,endCol,width = 0,
	    			loadWidth = scroller.children().width() - scroller.width() + 20;
	    		//	loadWidth = op._colSet.width + (op._colSet.count * op._colSet.fixed) - scroller.width() + op._fzColSet.width + (op._fzColSet.count * op._colSet.fixed);
	    		$.each(op.columns,function(i,col){
	    			if(!col.hidden && !col.freezeable){
	    				width += col._curWidth + op._colSet.fixed;
	    				endCol = col;
	    				if(scrollX < left && scrollX < loadWidth)
	    				{
	    					scrollX = width;
	    				}
	    				else {
	    					scrollX = width;
	    					return false;
	    				}
	    			}
	    		});
	    	}
	    	
	    	var endIndex = endCol ? endCol._curIndex : 0;
	    	//cehck列延迟加载模式
	    	if(op.columnLazyLoad)
	    	{
	    		if(grid.scrollLoadColumn(endCol ? endCol._i : 0,loadWidth))
	    			grid.hideColumn();
	    		else
	    			grid.hideColumn(op.columns[op._colLoad.start]._curIndex, endIndex);
	    	}
	    	else
		    	grid.hideColumn(0, endIndex);

	    	//触发横向滚动事件
	    	op.handler.scrollX && op.handler.scrollX.fire(grid,endIndex,scrollX);
	    	return grid;
	    },
	    //滚动到TD所在位置(横向)
	    scrollTo:function(column){
	    	var grid = this,op = this.op,colIndex = column._i;
	    	if(op.percentWidth || (op.allowFreezen && column.freezeable) || op.customTable){
	    		return op._hTr ? op._hTr.find("[_col='"+ colIndex + "']:first") : null;
	    	}
	    	
	    	var columns = this.getOrderColumns(true),width = 0,fzColSet = op._fzColSet,
	    		fixed = op._colSet.fixed;

	    	$.each(columns,function(i,col){
	    		if (!col.hidden) {
		    		if(col._i > colIndex)
		    			return false;
			    	width += col._curWidth + fixed;
	    		}
	    	});
	    	//计算滚动的位置
	    	var contentWidth = grid.getContent().width(),scroller = grid.getScroller(),
	    		scrollEnd = scroller.scrollLeft(),scrollLeft = width - contentWidth;
	    	if(scrollLeft > 0)
	    	{
		    	//判断是否超出当前范围
		    	var scrollStart = scrollEnd - contentWidth;
		    	if(scrollLeft < scrollStart || scrollLeft > scrollEnd)
		    		grid.scrollX(scroller,scrollLeft > 0 ? scrollLeft : 0, true);
	    	}
	    	else if(scrollEnd != scrollLeft)
	    		grid.scrollX(scroller,0, true);

	    	return op._hTr ? op._hTr.children("td[_col='"+ colIndex + "']") : null;
	    },
	    getScrollPanelWidth:function(){
	    	var grid = this,op = this.op;
	    	return grid.getContent().width() - op._fzColSet.width - (op._fzColSet.count * (op._colSet.fixed));
	    },
	    /** @description 根据范围隐藏列
	     *  @param {Number} start 开始数
	     *  @param {Number} end 结束数
	     *  @return {IGrid}
	     */
	    hideColumn: function (start, end)
	    {
	    	var style;
	    	if (end)
	    	{
		    	var arrHidden = [], pre = "table.igrid-itable ." + this.id + "-col";
	    		for (; start < end; start++)
	    		{
	    			arrHidden.push(start);
	    		}
	    		//注册style隐藏列
	    		if (arrHidden.length)
	    		{
//	    			style = "<style> " + pre + arrHidden.join("," + pre) + "{display:none !important;} </style>";
	    			style = "<style> " + pre + arrHidden.join("," + pre) + "{" +
	    				["padding:0","width:0px","border-width:0","overflow:hidden","word-break:keep-all","white-space:nowrap",""].join(" !important;")
	    				+ "} "+ pre + arrHidden.join(" div," + pre) + " div {display:none} </style>" ;
	    		}
	    	}
    		this.getColStylePanel().html(style || '');
    		return this;
	    },
	    hideColumns: function (start, end) {
	    	var style;
	    	if (end) {
		    	var arrHidden = [], pre = "table.igrid-itable ." + this.id + "-col";
	    		for (; start < end; start++)
	    		{
	    			arrHidden.push(start);
	    		}
	    		//注册style隐藏列
	    		if (arrHidden.length)
	    		{
	    			style = "<style> " + pre + arrHidden.join("," + pre) + "{" +
	    				["padding:0","width:0px","border-width:0","overflow:hidden","word-break:keep-all","white-space:nowrap",""].join(" !important;")
	    				+ "} "+ pre + arrHidden.join(" div," + pre) + " div {display:none} </style>" ;
	    		}
	    	}
	    	// 自定义的隐藏
	    	var colstyleCustom = this.getHead().find(".ccay-igrid-colstyle-custom");
	    	if (colstyleCustom.length) {
	    		colstyleCustom.html(style || "");
	    	} else {
    		 	$.create("div", "ccay-igrid-colstyle-custom").html(style || "").appendTo(this.getStylePanel());
	    	}
    		return this;
	    },
	    //初始化滚动加载列
	    initScrollLoadColumn:function(startIndex){
	    	var columns = this.getScrollLoadColumns(startIndex);
	    	if(columns && columns.length)
	    	{
	    		this.buildReloadColumns(columns);
	    		return true;
	    	}
	    },
	    //滚动加载列
	    scrollLoadColumn:function(startIndex){
	    	var columns = this.getScrollLoadColumns(startIndex);
	    	if(columns && columns.length)
	    	{
	    		this.reloadColumn(columns);
	    		return true;
	    	}
	    },
	    //根据开始位置获取需要加载的列
	    getScrollLoadColumns:function(startIndex){
	    	var op = this.op,fzNum = 0,width = 0,curColumns = [],fzColumns = [],
	    		isExpand,endIndex,col,columns = op.columns,colLoad = op._colLoad,
	    		len = columns.length,fzColSet = op._fzColSet,colSet = op._colSet;
	    		
	    	colSet.fixed || (colSet.fixed = 5);
	    	
	    	loadWidth = this.dom.width() - fzColSet.width - (fzColSet.count * (colSet.fixed));

	    	if(!colLoad || startIndex < colLoad.start)
	    	{
	    		loadWidth *= 2;
	    		isExpand = true;
	    		colLoad || (colLoad = op._colLoad = {});
	    	}
	    	for(var i = startIndex;i < len;i++)
	    	{
	    		col = columns[i];
	    		if(!col.hidden)
	    		{
	    			if(col.freezeable)
	    			{
	    				fzNum++;
	    				fzColumns.push(col);
	    			}
	    			else 
	    			{
	    				endIndex = col._i;
    					width += col._curWidth + colSet.fixed;
    					curColumns.push(col);
    					if(width > loadWidth)
    					{
    						if(!isExpand && col._i >= colLoad.end)
				    		{
			    				loadWidth *= 2;
			    				isExpand = true;
				    		}
				    		else
				    			break;
    					}
	    			}
	    		}
	    	}
	    	//判断是否重新加载
	    	if(isExpand || col._i > colLoad.end || col._i < colLoad.start)
	    	{
	    		//添加开始位置之前的冻结列
	    		if(startIndex > 0 && fzNum < fzColSet.count)
		    		fzNum = this.getFZColumn(0,startIndex,fzNum,fzColumns);
		    		
		    	//添加结束位置之后的冻结列
	    		if(fzNum < fzColSet.count)
	    			this.getFZColumn(i,len,fzNum,fzColumns);
	    			
	    		op._colLoad = {start:startIndex,end:endIndex};
	    		return fzColumns.concat(curColumns);
	    	}
	    },
	    //获取冻结列
	    getFZColumn:function(start,end,num,columns){
	    	var col,op = this.op;
	    	for(;start < end;start++)
	    	{
	    		if(num < op._fzColSet.count)
	    		{
		    		col = op.columns[start];
		    		if(!col.hidden && col.freezeable)
		    		{
		    			num++;
		    			columns.push(col);
		    		}
	    		}
	    		else
	    			return num;
	    	}
	    	return num;
	    },
	    //初始化需要加载的列
	    buildReloadColumns:function(columns){
	    	var grid = this,op = this.op,colFactory = factory.Column,
	    		tmpl = [],fzTmpl = [],headHtml = [], fzHeadHtml = [],
    			colSet=[],fzColSet=[];
	    		
	    	$.each(columns,function(i,col){
	    		if(op.allowFreezen && col.freezeable)
	    			colFactory.buildColHtml(grid,col,fzTmpl,fzHeadHtml,fzColSet)
	    		else
	    			colFactory.buildColHtml(grid,col,tmpl,headHtml,colSet);
	    	});
    		colFactory.buildRow(grid, op,tmpl,fzTmpl);
       		colFactory.buildHead(grid, headHtml,fzHeadHtml,colSet,fzColSet);
       		grid.hideColumn();
       		return grid;
	    },
	    //重新加载列
	    reloadColumn:function(columns){
	    	var focusTr = this.op._hTr,rowData;
	    	//设置焦点行
	    	if(focusTr)
	    	{
	    		rowData = this.getRowData(focusTr)
	    		rowData._focus = true;
	    	}
	    	this.op._loadType = "noScroll";
	    	this.buildReloadColumns(columns).reload();
	    	//设置焦点行
	    	if(rowData)
	    	{
	    		delete rowData._focus;
	    		this.op._hTr = this.getFocusRow();
	    	}
	    },
	    /** @description 根据设置同步滚动
	     *  @param {String} left 左边距
	     *  @param {String} top 上边距
	     *  @return {IGrid}
	     */
	    syncScroll: function (left,top)
	    {
        	left != null && this.scrollX(this.getScroller(), left);
        	left == 0 && this.hideColumn();
        	top != null && this.getBodyPanel().scrollTop(top);
            return this;
        },
        /** @description 获取分页信息
         *  @return {Object}
         */
        getPageInf: function ()
        {
        	return this.op.pagerOp.pageInf;
        },
        /** @description 获取重新加载后的对象
         *  @param {Boolean} isSearch 是否进行查询
         *  @param {Boolean} isRequest 是否进行请求
         *  @return {IGrid}
         */
        reload: function (isSearch, isRequest, isSort)
        {
        	var op = this.op, reloadType;
        	if (op.ajax) {
        		if (typeof(isSearch) == "string") {
	        		reloadType = isSearch;
	        		isSort = isRequest;
	        		isSearch = isRequest = null;
	        	} else {
	        		isSearch && (reloadType = "search");
        			!reloadType && isRequest && (reloadType = "request");
	        	}
        	} else {
        		isRequest = false;
        	}
        	switch (reloadType) {
        		case "operation":
        			op.pagerOp.pageInf.totalRows = 0;
        			isSearch = isRequest = true;
        			break;
        		case "search":
        			//!op._loadType && (op._loadType = "search");
        			op.pagerOp.pageInf.curPage = 1;
        			op.pagerOp.pageInf.totalRows = 0;
        			isSearch = isRequest = true;
        			break;
        		case "request":
        			isRequest = true;
        			break;
        		default:
        			//!op._loadType && (op._loadType = "reload");
        			this.base.reload.call(this);
        			break;
        	}
        	!op._loadType && (op._loadType = reloadType);
        	if (isRequest) {
        		if (!op.handler.beforeLoad || op.handler.beforeLoad.fire(this, op, isSearch) !== false) {
					this.base.request.call(this);
        		}
        	}
        	if (op.sort && isSort && !op.remoteSort && !op.lazyLoad && op.rowRender != "tree") {
        		op._isSort = true;
        	}
        	return this;
        },
        /** @description 获取绑定数据
         *  @param {Object} data 数据
         *  @return {IGrid}
         */
        reBind: function (data)
        {
        	this.base.reload.call(this,data);
        	return this;
        },
        /** @description 查询方法
         *  @param {Object} data 查询条件
         *  @return {IGrid}
         */
        search:function(param){
        	var op = this.op;
        	//更新参数
			if(param)
			{
				//合并默认请求条件
				if (op.ajax.params != null)
					param = $.extend(true, {}, op.ajax.params, param);
				op.ajax.data = param;
			}
			return this.reload(true);
        },
        setValue: function (data,copy)
        {
        	if(copy || this.op.dataCopy)
        		data = $.extend(true,[],data);
        	return this.reBind(data);
        },
        getValue:function(){
        	var clears = ["_index", "rowIdx", "_updFields"];
        	return this.op.Storage.filter({
        		copy:true,
        		fnHandle:function(item){
	        		$.each(clears,function(i,name){
	        			delete item[name];
	        		});
	        	}
        	});
        },
   		clearCache:function(){
   			this.op.Storage.clear();
   		},
   		/** @description 获取选中的行数据
	     *  @return {}
	     */
	    getSelectedRecords: function (fields,fnFilter)
	    {
	    	return this.op.Storage.getSelectedRecords(fields,fnFilter);
	    },
	    /** @description 获取选中的单行数据
	     *  @return {}
	     */
	    getSelectedRecord: function (fields,fnFilter)
	    {
	    	var records = this.getSelectedRecords(fields,fnFilter);
	    	return records.length ? records[0] : null;
	    },
	    // 表格不可用
	    disabled:function(disabled){
			if (disabled) {
				this.dom.addClass('disabled');
	    		this.op._disabled = true;
			} else {
				this.dom.removeClass('disabled');
				delete this.op._disabled;
			}
		},
		// 表格只读
		readonly: function (readonly) {
			if (readonly) {
				this.op._readonly = true;
			} else {
	    		delete this.op._readonly;
			}
		},
		// 重新初始化
		reInit: function (chanageGridOp) {
			var xGrid = Ccay.UI.XControl[this.type].fn, 
				oldOp = $.extend(true, {}, this.op),
				gridDom = this.dom,
				ajaxData = this.op.ajax && this.op.ajax.data,
				currGridRowOrder = this.op.rowRenderOp && this.op.rowRenderOp.order,
				gridOp;
			// 还原op设置
			this.setOp($.extend(true, {}, gridDom.data("defGridOp")));
			gridOp = this.op;
			// 清除结构
			gridDom.empty();
			DomClass.clear(this);
			// 应用当前的分页信息
			gridOp.pagerOp.pageInf = oldOp.pagerOp.pageInf;
			// 存在变更数据，则赋值个性化的grid设置；否则赋值默认的grid设置
			if (!$.isEmptyObject(chanageGridOp)) {				
				// 应用搜索模式
				if (!chanageGridOp.switchMode && oldOp.switchMode) {
					gridOp.switchMode = oldOp.switchMode;
				}
				if (chanageGridOp._hasColSort) {
					gridOp.sort = oldOp.sort;
					// 应用当前的行渲染优先级
					currGridRowOrder && (gridOp.rowRenderOp.order = currGridRowOrder);
					// 若是列拖拽，则需改变列位置
					gridOp.columns = chanageGridOp.columns;
					
				} else {
					// 将原始op替换成改变后的op
					Ccay.DataHelper.applyChangeData(gridOp, chanageGridOp, chanageGridOp.arrKey || {columns: "field"});
					this.colsort();
				}
			}
			// 添加原始的数据仓库
			gridOp.Storage = oldOp.Storage;
			// 如果是树形结构，添加树形结构仓库
			if(oldOp._treeStorage){
				gridOp._treeStorage = oldOp._treeStorage;
				gridOp._treeIniting = true;
			}
			// 保存搜索条件
			gridOp._ajax = gridOp.ajax;
			ajaxData && !$.isEmptyObject(ajaxData) && (gridOp._ajax.data = ajaxData);
			// 标示是重新初始化
			gridOp._reIniting = true;
			// 清除
			xGrid.plugin.fireAll("clear", this, gridOp, oldOp);
			// 新增数据进行合并
			gridOp.Storage.mergeNewData && gridOp.Storage.mergeNewData(!gridOp._requesting, gridOp);
			// 重新初始化op及重新绑定数据
			xGrid.base.initCtr.call(xGrid, this, gridOp);
			gridOp._reIniting = null;
		},
		// 显示错误验证信息
		showValidResult: function (value, validResult, cell) {
			validResult = [].concat(validResult);
			var lblError = $.create("label", "error"),
				cellPosition, cellHeight, errorHeight, errorPos,
				bodyPanel = this.getBodyPanel();
			// 滚动至显示列
			this.scrollTo(this.getColumnOp(cell));
			cell.addClass("igrid-servervalid-error");
			cellPosition = cell.position();
			cellHeight = cell.outerHeight();
			lblError.width(cell.outerWidth() - 20).text(validResult.join('\n')).appendTo(bodyPanel);
			errorHeight = lblError.outerHeight();
			// 若超过了容器高度，则显示在单元格的上面
			if (cellPosition.top + cellHeight + errorHeight >= bodyPanel.height()) {
				cellHeight = - errorHeight;
			}
			errorPos = {
				top: cellPosition.top + bodyPanel.scrollTop() + cellHeight,
				left: cellPosition.left + bodyPanel.scrollLeft()
			};
			lblError.css(errorPos);
			lblError.delay(3500).hide(500, function () {
				cell.removeClass("igrid-servervalid-error");
				lblError.remove();
			});
		},
		// 通过行索引及列的field属性获取单元格对象
		getCellByField: function (rowIdx, field) {
			var grid = this, row = grid.getRow(rowIdx), td = row.find('[field="' + field + '"]'), tds;
			if (!td.length) {
				row.find('[valueField="' + field + '"]').each(function () {
					td = $(this);
					if (grid.getColumnOp(td).editable !== false) {
						return false;
					}
				});
			}
			return td;
		},
		// 通过编辑控件获取行对象
		getEditRow: function (editCtr) {
			var td = editCtr.data('caller');
			return this.getCellRow(td);
		},
		// 设置滚动分页的每页显示的条数
		setScrollSize: function (containerHeight) {
			var op = this.op,
				scrollOp = op._scrollOp,
				totalSize = Math.ceil(containerHeight / op.rowHeight),
				currSize = scrollOp.pageSize;
			while (currSize <= totalSize) {
				currSize += scrollOp.pageSize;
			}
			return currSize;
		},
		//获取排序后有效的列
		getOrderColumns:function(includeInnerColumns){
			var fzCols = [],cols = [],op = this.op;
			$.each(op.columns,function(i,col){
				if(!includeInnerColumns && (col.inner || col.columnType || col.hidden))
					return;
				(op.allowFreezen && col.freezeable ? fzCols : cols).push(col);
			});
			return fzCols.concat(cols);
		},
		resize: function () {
			// 隐藏工具栏
			this.hideToolBar();
			// 修正横向滚动条
			factory.fixScrollToFullScreen(this);
			// 修正百分比模式下编辑器
			this.op.percentWidth && IGrid.Editor.fixActive(this);
		},
		changeResizeTip: function (grid) {
			grid = grid || this;
			var op = grid.op;
			// 百分比模式下，不提示冻结列信息
		 	if (!op.percentWidth) {
		 		var columns = op.columns,
					maxWidth = 0,
					scrollPanel = grid.getScroller();
			 	for (var i = 0, col; col = columns[i]; i++) {
			 		if (!col.inner) {
			 			colWidth = col._curWidth;
			 			(maxWidth < colWidth) && (maxWidth = colWidth);
			 		}
			 	}
			 	var noLockWidth = grid.getScrollPanelWidth();
				if (maxWidth + op._colSet.fixed > noLockWidth) {
					Ccay.UI.topBox("ccay.common.igrid.resizeMsg", false, false, null, 3000);
				}
				if (scrollPanel.width() >= scrollPanel.children().width()) {
					grid.hideColumn();
				}
		 	}
		},
		/** @description 排序设置
		 *  @param sortSetting {Object} 排序设置
	     */
		setSortSetting: function (sortFields, isRemoteSort) {
			var op = this.op;
			
			op._sortSetting = {
				sort: sortFields || Ccay.DataHelper.getObj("rowRenderOp.order",op), 
				isRemoteSort: (isRemoteSort != null ? isRemoteSort : op.remoteSort)
			};
		},
		clearSortSetting : function(){
			this.op._sortSetting = null;
		},
		getValueField: function (col) {
			if (typeof col == "string") {
				col = this.op._columnMap[col];
			}
			return col ? (col.valueField || col.field) : "";
		},
		//统计列
		totalColumn:function(){
			var grid=this,totalColumns = [],totalCounts={};
			$.each(grid.op.columns,function(i,col){					
				if(col.hidden){
					return;
				}
				if(col.totalCount){
					var valueField = col.valueField||col.field;
					totalColumns.push(valueField);
					totalCounts[valueField]=0;
				}
			});
			if(totalColumns.length){
				grid.getBodyTable().children("tfoot").remove();
				var totalRow = $('<tr class="grid-row row-noselect"></tr>').appendTo($("<tfoot></tfoot>").appendTo(grid.getBodyTable()));
				var allRecords = grid.getAllRecords();
				$.each(allRecords,function(i,data){
					$.each(totalColumns,function(k,field){
						try{
							var dataValue = Ccay.DataHelper.getObj(field,data);
							if(typeof dataValue=="string"){
								//取字符串最前面的数
								var tmpValue = dataValue.match("-?\\d+(\\.\\d+)*");
								if(!tmpValue){
									dataValue = 0;
								}else{
									dataValue = tmpValue[0];
								}
								
							}
							if(typeof dataValue=="string" && /^\d+$/.test(dataValue)){
								totalCounts[field]+=parseFloat(dataValue);
							}else if(typeof dataValue=="number"){
								totalCounts[field]+=dataValue;
							}
						}catch(e){
							
						}
					});
				});
				$.each(grid.op.columns,function(i,col){					
					if(col.hidden){
						return;
					}
					var td = $('<td></td>').addClass(col.attr["class"].replace(/\${.*}/g,"")),field=col.valueField||col.field;
					if(totalCounts[field]!==undefined){
						//统计行默认保留两位小数位，与field配置保留小数位一致 by twx305111 2016年1月20日
						if(col.format){
							var fraction= col.format.fraction;
							if (fraction == void 0){
								if("number" == col.type || "currency" == col.type  || "currencystr" == col.type){
									fraction = Ccay.Config.Format.decimalfraction;
								}else{
									fraction = 0;
								}
							}
							totalCounts[field] = parseFloat(totalCounts[field]).toFixed(fraction);
						}
						td.text(totalCounts[field]);
					}else if(col._ctype=="Seq" && grid.op.totalText){
						td.text($i18n(grid.op.totalText));
					}
					totalRow.append(td);
				});
			}
		},
		/**
		 * @description 清除关联下拉框的数据
		 * @param rowIdxOrTd {Number|Object} 行号或者单元格
		 * @param col {Object} 列
		 */
		clearConnectData:function(rowIdxOrTd, col){
			var rowIdx = typeof rowIdxOrTd == "number" ? rowIdxOrTd : this.getCellRow(rowIdxOrTd).attr("_row")*1;
			var connectMap = this.op._connectMap,grid = this;
			if(col.editorOp && col.editorOp.id && connectMap[col.editorOp.id] && connectMap[col.editorOp.id].child){
				$.each(connectMap[col.editorOp.id].child,function(i,childCol){
					var cell = grid.getCellByField(rowIdx,childCol.field);
					var rowData = grid.getRowData(rowIdx);
					rowData[childCol.valueField || childCol.field] = "";
					rowData[childCol.displayField || childCol.field] = "";
					cell.text("");
					childCol._editCtr && childCol._editCtr.hasClass("ccay-dropdown") && childCol._editCtr.data("old-val",{value:"",text:""});
					grid.clearConnectData(rowIdx,childCol);
				});
			}
		}
	};
    
    var flow = {
    	preInit: function (grid,op) {
    		// 设置索引序列
    		op.showSeq && op.columns.unshift({header:op.seqHeader,inner: true, width: op.seqWidth || (op.percentWidth ? '3%' : 30), _module: "igrid-seq",
    		_ctype: "Seq", headCss: 'grid-seq', cssName: 'grid-seq', content: '<span>${# data._seq || index}</span>', freezeable: op.allowFreezen });
    		// 初始化
    		factory.initHandler(op).initStyle(grid,op).initColumnMap(grid, op);;
    		factory.initConnectMap(grid,op);
    		if (!op._reIniting) {
    			op.rowCodeBegin.push("_rowNo++;");
    			op.rowCodeEnd.push("data._index = _rowNo;");
    		}
    	},
    	init: function (grid,op) {
    		// 绑定数据前，进行排序
    		op.handler.beforeBindData.add(function (grid, op, dataset, pageVO) {
        		// 数据排序
	           	if (op._isSort) {
	           		delete op._isSort;
	           		var sortOp = op.sort.split(" "),
	           			sortField = sortOp[0],
	           			sort = sortOp[1],
	           			cell = grid.getHeadTable().find("td[field='" + sortField + "']");
	           		if (!op.fnSort || op.fnSort.call(grid, sortField, sort, cell) !== false) {
	           			!op._loadType && (op._loadType = "sort");
	           			op.Storage.sort(sortField, sort);
	           		}
	           	}
        	});
    	},
    	build: function (grid, op) {
    		factory.Builder.init(grid, op);
    		//列设置初始化
    		if (op.customTable) {
    			op.allowResize = op.allowFreezen = op.showColumnIcon = false;
            	$.extend(factory.Column, factory.Common.Column, factory.Custom.Column);
            } else {
            	factory.Column = $.extend({}, factory.Common.Column);
            }
    	},
    	bindEvent:function(grid,op){
    		//列设置初始化
	        factory.Column.init(grid, op);
    		factory.EventBinder.init(grid,op);
    	},
    	initComplete:function(grid,op){
    		// 添加调整大小的标示
    		grid.dom.addClass("ccay-resize");
       		// 样式初始化
			//grid.updateStyle(1);
			// 设置默认的排序
			if (op.sort && !op.remoteSort) {
				op._isSort = true;
			}
    	},
    	initAjax:function(grid,op,ajax){
			var fnSetAjax = ajax.setAjax;
	       	ajax.setAjax = function(ajax){
	       		if(!fnSetAjax || fnSetAjax(ajax) !== false)
	       		{
	       			var url = ajax.url, sort;
	       			if (url) {
	       				if (url.indexOf("{0}") > 0) {
	       					ajax.url = url.formatText(op.pagerOp.pageInf.pageSize,op.pagerOp.pageInf.curPage,op.pagerOp.pageInf.totalRows); 
	       				} else {
	       					sort = factory.parseSortSetting(grid, op);
	       					op.pagerOp.pageInf.orderBy = sort || "default";
	       					op.pagerOp.pageInf.filter = op.pagerOp.pageInf.filter || encodeURIComponent("[]");
	       					ajax.url = url.formatField(op.pagerOp.pageInf);
	       				}
	       			}
	       		}
	       	};
	       	ajax.error = function(){
	       		op._errorRet = true;
	       		grid.reBind([]);
		    };
		},
		preBindData:function(grid,op,data,pageVO){
			//是否请求错误，不做处理
			if(op._errorRet){
				delete op._errorRet;
				return ;
			}
			if (pageVO) {
				if (data.length || pageVO.curPage == 1) {
					op.pagerOp.pageInf = pageVO;	
				} else {
					// 没有查询总数的，不做处理
					if (op.pagerOp.noTotalRows) {
						Ccay.UI.showMessage("ccay.common.igrid.noDatas");
					} else if (pageVO.curPage != 0) {
						// 当返回的数据是空时，将重新查询前一页的数据，若当前就是第一页时，不做任何操作
						op.pagerOp.pageInf.curPage = pageVO.totalPages;
						grid.reload("operation", true);
						// 标示重新加载
						op._reload = true;
						return false;
					}
				}
			}
			if(op.pagerOp.pageInf && op.pagerOp.pageInf.filterStr){
				op.pagerOp.pageInf.filter = op.pagerOp.pageInf.filterStr.encodeURI();
			}else{
				op.pagerOp.pageInf.filter = "[]".encodeURI();
			}
			var pageInf = op.pagerOp.pageInf,
				columns = op.columns;
            op.startIndex = op.serialSeq ? (pageInf.curPage -1) * pageInf.pageSize + 1 : 1;
            // 设置总记录数
           	pageInf.totalRows == 0 && op.Storage.len() && (pageInf.totalRows = op.Storage.len());
           	// 处理复制渲染值
           	if (columns && data && !op._staticSort) {
           		// 遍历数据集，执行数据处理
   				$.each(data, function (recordIndex, record) {
   					op.handler.dataHandler.fire(record, grid, op, data);
   				});
           	}
           	delete op._staticSort;
		},
		bindData:function(grid,op,data){
			// 重新加载时，不执行绑定数据操作
			if (!op._reload) {
				data = data || [];
				grid.getHeadTable().find(".igrid-head .grid-select")[!data.length?'addClass':'removeClass']("grid-selected-disabled");
				op.lastIndex = op.startIndex + data.length - 1;
	            var content = Ccay.UI.tmplList(op.tmpl, data,null,op.startIndex,null,{_rowNo: -1, _grid: grid}, true);
	            grid.getDataBody().html(content);
			}
		},
		bindDataComplete:function(grid,op){
			// 存在重新加载的标示，则去除
			if (op._reload) {
				op._reload = null;
			}else {
				grid.totalColumn();
				//自定义行渲染
				if (op.fnRenderRow) {
	                grid.getDataBody().children('tr.grid-row').each(function (i) {
	                        var row = $(this),data = op.Storage.at(i);
	                        op.fnRenderRow && op.fnRenderRow.call(grid, row, data, i);
	                });
	            }
	            // 更新滚动位置
	        	if (op.autoScroll) {
	        		if (!op._loadType || (op._loadType != "noScroll" && op._loadType != "sort")) {
	        			grid.syncScroll(0, 0);
	        		}
	        		op._loadType = null;
	        	}
	        	// 缓存当前页可选数据的条数
				op._prevSelCount = grid.getRows(":not(.row-noselect):not(.grid-row-group)").length - 1;
				// 设置表头的选中状态
				op._prevSelCount && grid.setSelectHeader(true);
	        	// 更新样式
	        	grid.updateStyle();
			}
		}, 
		complete:function(grid,op){

		}
    };
    var XGrid = Ccay.UI.XControl("XGrid",flow,config,manager,"Table");
    
     $.fn.igrid = function (op, datas) {
        datas && (op.dataset = datas);
        var grid = new XGrid(this, op);
        return this;
    }
})(Ccay.UI.IGrid);